<?php
// +----------------------------------------------------------------------
// | ThinkPHP
// +----------------------------------------------------------------------
// | Copyright (c) 2008 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$

// Think静态类库
class Think extends Base {

    private static $_instance = array();
    private static $_file = array();
    private static $_time   =   array();
    private static $_mem    =   array();
    private static $_validate = array(
        'require'=> '/.+/', //匹配任意字符，除了空和断行符
        'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/',
        'url' => '/^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/',
        'currency' => '/^\d+(\.\d+)?$/',
        'number' => '/\d+$/',
        'zip' => '/^[1-9]\d{5}$/',
        'integer' => '/^[-\+]?\d+$/',
        'double' => '/^[-\+]?\d+(\.\d+)?$/',
        'english' => '/^[A-Za-z]+$/',
    );

    /**
     +----------------------------------------------------------
     * 系统自动加载ThinkPHP基类库和当前项目的model和Action对象
     * 并且支持配置自动加载路径
     +----------------------------------------------------------
     * @param string $classname 对象类名
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    public static function load($classname)
    {
        // 自动加载当前项目的Actioon类和Model类
        if(substr($classname,-5)=="Model") {
            if(!Think::import('@.Model.'.$classname)){
                // 如果加载失败 尝试加载组件Model类库
                Think::import("@.*.Model.".$classname);
            }
        }elseif(substr($classname,-6)=="Action"){
            if(!Think::import('@.Action.'.$classname)) {
                // 如果加载失败 尝试加载组件Action类库
                Think::import("@.*.Action.".$classname);
            }
        }else {
            // 根据自动加载路径设置进行尝试搜索
            if(C('AUTO_LOAD_PATH')) {
                $paths	=	explode(',',C('AUTO_LOAD_PATH'));
                foreach ($paths as $path){
                    if(Think::import($path.$classname)) {
                        // 如果加载类成功则返回
                        return ;
                    }
                }
            }
        }
        return ;
    }

    /**
     +----------------------------------------------------------
     * 取得对象实例 支持调用类的静态方法
     +----------------------------------------------------------
     * @param string $className 对象类名
     * @param string $method 类的静态方法名
     * @param array $args 调用参数
     +----------------------------------------------------------
     * @return object
     +----------------------------------------------------------
     */
    static public function instance($className,$method='',$args=array())
    {
        if(empty($args)) {
            $identify   =   $className.$method;
        }else{
            $identify   =   $className.$method.to_guid_string($args);
        }
        if (!isset(self::$_instance[$identify])) {
            if(class_exists($className)){
                $o = new $className();
                if(method_exists($o,$method)){
                    if(!empty($args)) {
                        self::$_instance[$identify] = call_user_func_array(array(&$o, $method), $args);;
                    }else {
                        self::$_instance[$identify] = $o->$method();
                    }
                }
                else
                    self::$_instance[$identify] = $o;
            }
            else
                halt(L('_CLASS_NOT_EXIST_'));
        }
        return self::$_instance[$identify];
    }

    /**
     +----------------------------------------------------------
     * 加载文件 并编译处理
     * 第二次直接读取编译后的文件
     +----------------------------------------------------------
     * @param string $filename 要加载的文件名
     * @param string $cachefile 缓存后的文件名
     +----------------------------------------------------------
     * @return boolen
     +----------------------------------------------------------
     */
    public static function includeX($filename,$cachefile='') {
        static $_importFiles = array();
        if (!isset($_importFiles[$filename])) {
            if(''==$cachefile)
                $cachefile  =   TEMP_PATH.'$'.md5($filename).'.php';
            if(file_exists($cachefile)) {
                // 存在编译文件
                include $cachefile;
            }elseif(file_exists($filename)){
                $content    =   php_strip_whitespace($filename);
                eval('?>'.$content);
                // 保存编译后的文件
                file_put_contents($cachefile,$content);
            }else{
                return false;
            }
            $_importFiles[$filename] = true;
        }
        return true;
    }

    /**
     +----------------------------------------------------------
     * 导入所需的类库 支持目录和* 同java的Import
     * 本函数有缓存功能
     +----------------------------------------------------------
     * @param string $class 类库命名空间字符串
     * @param string $baseUrl 起始路径
     * @param string $appName 项目名
     * @param string $ext 导入的文件扩展名
     * @param string $subdir 是否导入子目录 默认false
     +----------------------------------------------------------
     * @return boolen
     +----------------------------------------------------------
     */
    public static function import($class,$baseUrl = '',$ext='.class.php',$subdir=false)
    {
          $importFile    =   strtolower($class.$baseUrl);
          if(isset(self::$_file[$importFile]))
                return true;
          else
                self::$_file[$importFile] = true;
          //echo $baseUrl.$class.'<br/>';
          //if (preg_match('/[^a-z0-9\-_.*]/i', $class)) throw_exception('Import非法的类名或者目录！');
          if( 0 === strpos($class,'@'))     $class =  str_replace('@',APP_NAME,$class);
          if(empty($baseUrl)) {
                // 默认方式调用应用类库
                $baseUrl   =  dirname(LIB_PATH);
          }else {
                //相对路径调用
                $isPath =  true;
          }
          $class_strut = explode(".",$class);
          if('*' == $class_strut[0] || isset($isPath) ) {
            //多级目录加载支持
            //用于子目录递归调用
          }
          elseif(APP_NAME == $class_strut[0]) {
              //加载当前项目应用类库
              $class =  str_replace(APP_NAME.'.',LIB_DIR.'.',$class);
          }
          elseif(in_array(strtolower($class_strut[0]),array('think','org','top','com'))) {
              //加载ThinkPHP基类库或者公共类库
              // think 官方基类库 org 第三方公共类库 com 企业公共类库 top 2代企业类库
              $baseUrl =  THINK_PATH.'/'.LIB_DIR.'/';
          }else {
              // 加载其他项目应用类库
              $class    =   substr_replace($class, '', 0,strlen($class_strut[0])+1);
              $baseUrl =  APP_PATH.'/../'.$class_strut[0].'/'.LIB_DIR.'/';
          }
          if(substr($baseUrl, -1) != "/")    $baseUrl .= "/";
          $class    =   str_replace(array('.','#'), array('/','.'), $class);
          $classfile = $baseUrl.$class.$ext;
          if(false !== stripos($classfile,'*') || false !== stripos($classfile,'?') ) {
                // 导入匹配的文件
                $match  =   glob($classfile);
                if($match) {
                   foreach($match as $key=>$val) {
                       if(is_dir($val)) {
                           // 导入子目录
                           if($subdir) selft::import('*',$val.'/',$ext,$subdir);
                       }else{
                           if($ext == '.class.php') {
                                if(!class_exists($class,false)) {
                                    return require_cache($val);
                                }else{
                                    return false;
                                }
                           }
                            //导入类库文件
                            $result =   require_cache($val);
                       }
                   }
                   return $result;
                }else{
                   return false;
                }
          }else{
                if($ext == '.class.php') {
                    if(!class_exists($class,false)) {
                        return require_cache($classfile);
                    }else{
                        return false;
                    }
                }else{
                    //导入目录下的指定类库文件
                    return require_cache($classfile);
                }
          }
    }

    /**
     +----------------------------------------------------------
     * 设置缓存数据
     +----------------------------------------------------------
     * @param string $name 缓存标识
     * @param mixed $value 缓存内容
     * @param integer $expire  有效期 单位为秒 -1 永久
     * @param string $type 缓存方式
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    public static public function setCache($name,$value,$expire='',$type='') {
        Think::import('Think.Util.Cache');
        //取得缓存对象实例
        $cache  = Cache::getInstance($type);
        if(is_null($value)) {
            // 删除缓存
            $result =   $cache->rm($name);
            return $result;
        }else{
            // 缓存数据
            $cache->set($name,$value,$expire);
        }
        return ;
    }

    /**
     +----------------------------------------------------------
     * 获取缓存数据
     +----------------------------------------------------------
     * @param string $name 缓存标识
     * @param string $type 缓存方式
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public static public function getCache($name,$type='') {
        Think::import('Think.Util.Cache');
        //取得缓存对象实例
        $cache  = Cache::getInstance($type);
        // 获取缓存数据
        return $cache->get($name);
    }

    /**
     +----------------------------------------------------------
     * 快速文件数据读取和保存 针对简单类型数据 字符串、数组
     +----------------------------------------------------------
     * @param string $name 缓存标识
     * @param mixed $value 缓存内容
     * @param integer $expire  有效期
     * @param string $path 缓存路径
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    static function fastCache($name,$value='',$expire=-1,$path=DATA_PATH) {
        static $_cache = array();
        $filename   =   $path.$name.'.php';
        if('' !== $value) {
            if(is_null($value)) {
                // 删除缓存
                $result =   unlink($filename);
                if($result) {
                    unset($_cache[$name]);
                }
                return $result;
            }else{
                // 缓存数据
                $content   =   "<?php\nif (!defined('THINK_PATH')) exit();\n//".sprintf('%012d',$expire)."\nreturn ".var_export($value,true).";\n?>";
                $result  =   file_put_contents($filename,$content);
                $_cache[$name]   =   $value;
            }
            return ;
        }
        if(isset($_cache[$name])) {
            return $_cache[$name];
        }
        // 获取缓存数据
        if(file_exists($filename) && false !== $content = file_get_contents($filename)) {
            $expire  =  (int)substr($content,44, 12);
            if($expire != -1 && time() > filemtime($filename) + $expire) {
                //缓存过期删除缓存文件
                unlink($filename);
                return false;
            }
            $value  =    eval(substr($content,57,-2));
            $_cache[$name]   =   $value;
        }else{
            $value  =   false;
        }
        return $value;
    }

    /**
     +----------------------------------------------------------
     *  区间调试开始
     +----------------------------------------------------------
     * @param string $label  标记名称
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    public static function debugStart($label='')
    {
        self::$_time[$label]['_beginTime'] = microtime(TRUE);
        if ( MEMORY_LIMIT_ON )  self::$_mem[$label]['memoryUseStartTime'] = memory_get_usage();
    }

    /**
     +----------------------------------------------------------
     *  区间调试结束，显示指定标记到当前位置的调试
     +----------------------------------------------------------
     * @param string $label  标记名称
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    public static function debugEnd($label='')
    {
        self::$_time[$label]['_endTime'] = microtime(TRUE);
        echo '<div style="text-align:center;width:100%">Process '.$label.': Times '.number_format(self::$_time[$label]['_endTime']-self::$_time[$label]['_beginTime'],6).'s ';
        if ( MEMORY_LIMIT_ON )  {
            self::$_mem[$label]['memoryUseEndTime'] = memory_get_usage();
            echo ' Memories '.number_format((self::$_mem[$label]['memoryUseEndTime']-self::$_mem[$label]['memoryUseStartTime'])/1024).' k';
        }
        echo '</div>';
    }

    /**
     +----------------------------------------------------------
     *  数据类型和格式判断
     +----------------------------------------------------------
     * @param mixed $value  数据
     * @param string $type  比较类型或者格式类型
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    static function is($value,$type) {
        static $_type   =   array('null','int','integer','float','real','bool','numberic','string','object','array','resource','scalar','file','dir','link','callable');
        if(in_array(strtolower($type),$_type,true)) {
            // 判断数据类型
            $fun    =   'is_'.strtolower($type);
            return $fun($value);
        }elseif(is_object($value)){
            return  ($value instanceof $type);
        }else{
            return NULL;
        }
    }

    /**
     +----------------------------------------------------------
     * 验证数据
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $value  要验证的数据
     * @param string $rule 验证规则
     * @param string $type   验证方式
     * 包含 regex function class 默认为regex
     +----------------------------------------------------------
     * @return boolean
     +----------------------------------------------------------
     */
    static public function validate($value,$rule,$type='regex') {
        switch(strtolower($type)) {
            case 'function':
                return $rule($value);
            case 'class':
                $class  =   new $rule();
                return $class->isValid($value);
            case 'regex':
            default:
                if(isset(self::$_validate[strtolower($rule)])) {
                    $rule   =   self::$_validate[strtolower($rule)];
                }
                return preg_match($rule,$value)===1;
        }
    }

    /**
     +----------------------------------------------------------
     *  添加验证因子
     +----------------------------------------------------------
     * @param string $name  验证名称
     * @param string $value  验证规则
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    static function addValidator($name,$value) {
        self::$_validate[strtolower($name)] =   $value;
    }

    /**
     +----------------------------------------------------------
     *  批量添加验证因子
     +----------------------------------------------------------
     * @param array $items  验证因子
     * Think::addValidators(array('Email'=>'/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/'...));
     +----------------------------------------------------------
     * @return void
     +----------------------------------------------------------
     */
    public static function addValidators($items=array()) {
        self::$_validate    =   array_merge(self::$_validate,$items);
    }

    /**
     +----------------------------------------------------------
     *  Think版本比较
     +----------------------------------------------------------
     * @param string $version  版本号
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public static function compareVersion($version) {
        return version_compare($version, THINK_VERSION);
    }

    /**
     +----------------------------------------------------------
     *  清空Think目录和缓存
     +----------------------------------------------------------
     * @param string $path  清空目录
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */
    public static function clearCache($path=RUNTIME_PATH) {
        Think::import("ORG.Io.Dir");
        Dir::del($path);
    }
}
?>